package com.egghiro.framework.j2se.game.core.view.canvas;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;

import com.egghiro.framework.j2se.game.core.view.SImage;

/**
 *
 * @project SGame
 * @author huangguoning
 * @email：egg1412@gmail.com
 * @version 0.1
 */
public abstract class DoubleBufferCanvas extends Canvas {
    private byte[] lock = new byte[0];
    private SImage offBuffer;
    private SGraphics offGraphics;

    public DoubleBufferCanvas() {
    }

    public DoubleBufferCanvas(int width, int height) {
        super();
        setSize(width, height);
    }

    @Override
    public final void update(Graphics g) {
        if (isVisible()) {
            if (offGraphics == null) {
                initialGraphics();
            }
            try{
                offGraphics.clearRect(0, 0, getWidth(), getHeight());
                paint(offGraphics);
            } catch(NullPointerException e){
                // TODO 2013/04/09 try-catch追加
            }

        }
    }

    /**
     * Flush offBuffer to Screen
     */
    public final void flushGraphics() {
        if (isVisible()) {
            super.getGraphics().drawImage(offBuffer.getBufferedImage(), 0, 0, this);
        }
    }

    /**
     * Flushes the specified region of the off-screen buffer to the display If the specified region
     * extends beyond the current bounds of the GameCanvas, only the intersecting region is flushed.
     * No pixels are flushed if the specified width or height is less than 1.
     *
     * @param x
     * @param y
     * @param width
     * @param height
     */
    public final void flushGraphics(int x, int y, int width, int height) {
        if (isVisible()) {
            // TODO
            // super.getGraphics().drawImage(offBuffer.getBufferedImage(), 0, 0, this);
        }
    }
    
    /**
     * Simple method to update double buffer
     */
    public final void updateDoubleBuffer(){
        update(getGraphics());
        flushGraphics();
    }

    @Override
    public void setSize(int width, int height) {
        super.setSize(width, height);
        offBuffer = null;
        offGraphics = null;
    }

    public void initialGraphics() {
        offGraphics = getSGraphics();
    }

    public SGraphics getSGraphics() {
        SGraphics g = null;
        if (createIfOffbufferIsNull()) {
            g = offBuffer.getSGraphics();
            // g.setColor(Color.BLACK);
            // g.setFont(Font.decode(null));
        }
        return g;
    }

    protected SGraphics getOffGraphics() {
        if (offGraphics == null) {
            initialGraphics();
        }
        return offGraphics;
    }

    protected boolean createIfOffbufferIsNull() {
        if (offBuffer == null) {
            synchronized (lock) {
                if (offBuffer == null) {
                    offBuffer = SImage.createImage(getWidth(), getHeight());
                }
            }
        }
        return (offBuffer != null);
    }

    public abstract void paint(SGraphics g);
}
